/////////////////////////////////////////////////////////////////////////////
// Copyright (c)2016 ALTA Incorporated                                     //
// All Rights Reserved                                                     //
// THIS IS UNPUBLISHED PROPRIETARY SOURCE CODE of ALTA Inc.                //
// The copyright notice above does not evidence any actual or intended     //
// publication of such source code.                                        //
// No part of this code may be reproduced, stored in a retrieval system,   //
// or transmitted, in any form or by any means, electronic, mechanical,    //
// photocopying, recording, or otherwise, without the prior written        //
// permission of ALTA                                                      //
/////////////////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////////////
// Name of module : mcu_ini_cfg                                            //
// Project group  : mcu_ini_cfg                                            //
// Func           : ini mcu remap                                          //
// Author         : yinliang                                               //
// Simulator      : NCsim/LINUX64                                          //
// version 1.0    : made in Date: 2016.02.18                               //
/////////////////////////////////////////////////////////////////////////////

`timescale 1ns/10ps

module mcu_ini_cfg      (input  wire        i_clk                             ,//from external oscilator
                         input  wire        i_reset_n                         ,//power on reset    
                         input  wire [23:0] i_flash_bias                      ,                                                
                         output wire        o_tck                             ,//The tck clock output
                         output reg         o_tms                             ,//
                         output reg         o_tdi                             ,//
                         input  wire        i_tdo                             ,// 
                         output wire        o_flash_csn                       ,
                         output wire        o_flash_sclk                      ,
                         output reg         o_flash_sdi                       ,
                         input  wire        i_flash_sdo                       ,
                        // output reg         o_flash_si_oe                     ,
                         output reg         o_ram_wr                          ,
                         output reg  [13:0] o_ram_addr                        ,
                         output wire [31:0] o_ram_wdata                       ,                        
                         output reg         o_ini_ip                          //low indicate ini remap finished
                         );        

parameter        CLKDIV_NUM           = 4'b0100                               ;  

parameter        NOP                  = 3'b000                                ,    
                 RESET_JTAG_TAP       = 3'b010                                ,  
                 ISC_DPACC_CTST       = 3'b011                                ,                                             
                 ISC_DPACC_AP         = 3'b100                                ,                   
                 ISC_APACC_0          = 3'b101                                ,
                 CFG_FINISH           = 3'b110                                ,
                 ISC_APACC_1          = 3'b111                                ;
  
parameter        CNT_TMS_REG_IR       = 4'h3                                  ;                                                                          
parameter        CNT_TMS_REG_IRDR     = 6'h31                                 ;

parameter        ISC_DPACC_IR         = 4'b1010                               ,  
                 ISC_APACC_IR         = 4'b1011                               ;   
                 

parameter        CNT_RESET            = 9'd360                                ;                 
                                                                              
parameter        IDLE                 = 4'b0000                               ,         
                 READ_STATUS_REG      = 4'b0001                               ,         
                 HOLD_READ_STATUS     = 4'b0011                               ,  
                 AS_READ_HEADER       = 4'b0010                               ,  
                 HOLD_AS_READ_HEADER  = 4'b0110                               , 
                 AS_READ              = 4'b0101                               ,
                 HOLD_AS              = 4'b0100                               ;                 
                                                                                            
                                                                                            
parameter        CMD_RDDATA           =  8'h03                                ,                                                               
                 CMD_READ_STATUS_REG  =  8'h05                                ;                               
 
                 
///////////////////////////////////////////////////////////////////////////////////
reg [2:0]  curr_tap_state                                                     ; 
reg [2:0]  next_tap_state                                                     ; 
reg [5:0]  cnt_state_incdr                                                    ; 
reg [2:0]  cnt_reset_tap                                                      ; 
reg        reset_stretch                                                      ;
reg [8:0]  cnt_reset_stretch                                                  ;     
reg        first_dpacc                                                        ; 



reg        clk_div                                                            ; 
reg [2:0]  counter                                                            ; 
reg [2:0]  curstate                                                           ; 
reg [2:0]  nxtstate                                                           ; 
reg [31:0] byte_length                                                        ; 
reg [7:0]  cnt_header_bit                                                     ; 
reg        flash_csn                                                          ; 
reg        spiclk_en                                                          ; 
reg [3:0]  cnt_read_status                                                    ; 
reg [7:0]  cmd_reg                                                            ; 
reg [23:0] addr_reg_flash                                                     ; 
reg [2:0]  bit_cnt8_cmd                                                       ; 
reg [4:0]  bit_cnt24_addr                                                     ; 
reg        tx_cmd_en                                                          ; 
reg        tx_addr_en                                                         ; 
reg        flash_busy                                                         ; 
reg [5:0]  cnt_cmd_addr_as                                                    ; 
reg [4:0]  cnt_ram_bit                                                        ;
reg        as_data_vld                                                        ;
reg        as_data                                                            ;
reg        read_status_done                                                   ; 
reg        read_header_done                                                   ;
reg        ini_ip_sync1                                                       ; 
reg        ini_ip_sync2                                                       ; 
reg        remap_begin_d1                                                     ; 
reg        remap_begin_d2                                                     ; 
reg        illegal_length                                                     ;
reg        ini_ip                                                             ;     
//////////////////////////////////////////////////////////////////////////////////                                       
wire [9:0]  wm_tms_reg_ir                                                     ;
wire [49:0] wm_tms_reg_irdr                                                   ;    
wire [3:0]  wm_isc_dpacc_ir                                                   ;
wire [3:0]  wm_isc_apacc_ir                                                   ;  
wire [34:0] wm_isc_dpacc_dr                                                   ;                                                                               
wire [34:0] wm_isc_apacc_dr_0                                                 ;                                                                                      
wire [34:0] wm_isc_apacc_dr_1                                                 ;        
wire [34:0] wm_isc_apacc_dr_ctst                                              ;
wire        w_rst_n                                                           ;   
wire [3:0]  wm_clkdiv_num                                                     ;                           
wire        clk                                                               ;

////////////////////////////////////////////////////////////////////////////////////////
assign w_rst_n              = reset_stretch                                   ;
assign wm_tms_reg_ir        = {4'b1100,3'b000,3'b110}                         ;                                                                                  
assign wm_tms_reg_irdr      = {wm_tms_reg_ir,3'b100,34'b0000000,3'b110}       ;                                                                                
assign wm_isc_dpacc_ir      = ISC_DPACC_IR                                    ;                                                                                 
assign wm_isc_apacc_ir      = ISC_APACC_IR                                    ;                                                                                  
assign wm_isc_apacc_dr_0    = {32'h4001_6014,2'b01,1'b0}                      ; //TAR = 32'h4001_6014,DPaddr = 2'b01 ,select TAR(transfer_address register)                                                                        
assign wm_isc_apacc_dr_1    = {32'h0000_0003,2'b11,1'b0}                      ; //DRWR = 32'h0000_0003 ,select DRWR(Data read/write register)                                                                                    
assign wm_isc_dpacc_dr      = 35'h0000004                                     ;//apsel = 0x00,banksel = 0x0,[2:1]= 2'b10 for addr 0x8 of apselect register        
assign wm_isc_apacc_dr_ctst = 35'h2a0000002                                   ;
//assign w_config_trigger = (cnt_reset_stretch == CNT_RESET)                    ;  
assign clk                  = (wm_clkdiv_num == 3'b000) ? i_clk : clk_div                                                                              ; 
assign w_flash_free         = (curstate == IDLE) ||(curstate == HOLD_READ_STATUS)||(curstate == HOLD_AS_READ_HEADER)||(curstate == HOLD_AS)            ; 
assign w_spiclk_vld         = (curstate == READ_STATUS_REG) ||(curstate == AS_READ) || (curstate == AS_READ_HEADER)                                    ; 
assign w_spiclk_clr         = read_header_done || read_status_done ||((cnt_ram_bit == 5'h1e) && (o_ram_addr == (byte_length >> 2) -1)) || illegal_length ; 
assign w_addr_mode          = (curstate == AS_READ) || (curstate == AS_READ_HEADER)                                                                    ; 
assign wm_clkdiv_num        = CLKDIV_NUM ;
GCKESF  TCK_GATE   (.TE(1'b0),.E(o_ini_ip),.CK(clk_div  ),.Q(o_tck))                ; 
GCKESF  SCK_GATE   (.TE(1'b0),.E(spiclk_en),.CK(clk_div  ),.Q(o_flash_sclk))      ;
//assign o_tck  = o_ini_ip && i_clk                                              ; 
assign o_flash_csn          = flash_csn                                           ;
//assign o_ini_ip             = illegal_length ? 1'b0 : ini_ip                      ;
                                                                                                                                                                                                                            
///////////////////////////////////////////////////////////////////////////////////

always@(negedge i_clk or negedge i_reset_n)                                         
    begin                                                                           
       if(!i_reset_n)                                                               
           reset_stretch <= 0;   
       else if(cnt_reset_stretch == CNT_RESET)
           reset_stretch <= 1;  
    end                
                              
always@(negedge i_clk or negedge i_reset_n)                                     
    begin                                                                       
       if(!i_reset_n)                                                           
           cnt_reset_stretch <= 0;                                                  
       else if(cnt_reset_stretch == CNT_RESET)                                  
           cnt_reset_stretch <= 0; 
       else if(!reset_stretch)
           cnt_reset_stretch <= cnt_reset_stretch + 1;                                             
    end                                                                         

///////////////////////////////////////////////////////////////////////////////////////////////////////////////////               
//////////////////////////////////////SPI master ctrl ////////////////////////////////////////////////////////////               
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////      

reg clk_div_disable ;

always@(posedge i_clk or negedge w_rst_n)        
    begin                                           
        if (!w_rst_n)	
            clk_div_disable <=0;
        else if((counter == ((wm_clkdiv_num >> 1) -1)) && !clk_div && !ini_ip_sync1 && ini_ip_sync2)              
            clk_div_disable <= 1;
    end
                                                                                                                                           
always@(posedge i_clk or negedge w_rst_n)        
    begin                                           
        if (!w_rst_n)	                              
            counter <= 0;  
        else if(counter == ((wm_clkdiv_num >> 1) -1)) 
            counter <= 0;                        
        else if(!clk_div_disable)                                        
            counter <= counter + 1;                  
    end                                             

always@(posedge i_clk or negedge w_rst_n)        
    begin                                           
        if (!w_rst_n)	                              
            clk_div <= 0;                          
        else if(counter == ((wm_clkdiv_num >> 1) -1))                                       
            clk_div <= !clk_div;                  
    end                                             

                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                 
always@(posedge clk_div or negedge w_rst_n)                 
    begin                                                   
        if (!w_rst_n)                                     
            begin                                           
                ini_ip_sync1 <= 0;                              
                ini_ip_sync2 <= 0;                              
            end                                             
        else                                                
            begin                                           
                ini_ip_sync1 <= o_ini_ip ;                       
                ini_ip_sync2 <= ini_ip_sync1;                       
            end                                             
    end                                                     


always@(posedge clk_div or negedge w_rst_n)                                                              
    begin                                                                                                
        if (!w_rst_n)                                                                                      
            curstate <= IDLE;                                                                                
        else                                                                                               
            curstate <= nxtstate;                                                                            
    end                                                                                                  
 
 
always@( * )                                                                                         
    begin                                                                                                
        case (curstate)        
            IDLE:                 begin  
            	                        if(ini_ip_sync1 && !ini_ip_sync2) 
                                          nxtstate = READ_STATUS_REG;
                                      else
                                          nxtstate = IDLE;      
                                  end 
                                             	          	                                                                                 
           READ_STATUS_REG:      begin
                                     if(read_status_done)
                                         nxtstate = HOLD_READ_STATUS;         
                                     else
                                         nxtstate = READ_STATUS_REG;   
                                 end                                     
                                 
           HOLD_READ_STATUS:     begin
                                     if(flash_busy == 1'b0)                                                                                                            
                                         nxtstate = AS_READ_HEADER;                                                           
                                     else                                               
                                         nxtstate = READ_STATUS_REG;                    
                                 end
                                 
          AS_READ_HEADER  :      begin                                                                                                          
                                      if(read_header_done)   
                                          nxtstate = HOLD_AS_READ_HEADER;  
                                      else if(illegal_length)     
                                      	  nxtstate = HOLD_AS;       
                                      else                                                 
                                          nxtstate = AS_READ_HEADER ;                     
                                 end                         
                                 
          HOLD_AS_READ_HEADER:   begin
           	                          nxtstate = AS_READ;
           	                     end                     
                                                                                                   
            AS_READ :            begin                                                                                  
                                     if((cnt_ram_bit == 5'h1e) && (o_ram_addr == (byte_length >> 2) -1 ))  
                                         nxtstate = HOLD_AS;                                                                          
                                     else
                                         nxtstate = AS_READ;
                                 end                        
                                                                                                                                                                                                                                                                                                                                                         
          HOLD_AS:               begin 
          	                          if(!ini_ip_sync1 && ini_ip_sync2)
          	                              nxtstate =  IDLE;
          	                          else                                                 
                                          nxtstate = HOLD_AS;                                
                                 end                                     
         
         default:               nxtstate   =   IDLE;
         
        endcase
    end 
/*
always@(posedge clk_div or negedge w_rst_n)                                         
    begin                                                                           
        if (!w_rst_n)                                                               
            o_flash_si_oe <= 0;                                                       
        else if(((curstate == AS_READ)|| (curstate == AS_READ_HEADER)) &&(cnt_cmd_addr_as != 6'b000000))             
            o_flash_si_oe <= 1;                                                       
        else                                                                        
            o_flash_si_oe <= 0;                                                       
    end                                                                             
*/

always@(posedge clk_div or negedge w_rst_n)          
    begin                                            
        if (!w_rst_n)   
            cnt_header_bit <= 0;
        else if((curstate == AS_READ_HEADER) && !flash_csn)
            cnt_header_bit <= cnt_header_bit + 8'h01;
        else
            cnt_header_bit <= 0;
    end                           

always@(posedge clk_div or negedge w_rst_n)                                
    begin                                                                  
        if (!w_rst_n)   
            byte_length <= 0;
        else if(cnt_header_bit >= 8'h20 && cnt_header_bit <= 8'h3f) 
            byte_length <= {byte_length[30:0],i_flash_sdo};                                                                       
    end                                                                                



always@(posedge clk_div or negedge w_rst_n)                                
    begin                                                                  
        if (!w_rst_n)   
            illegal_length <= 0;
        else if((cnt_header_bit == 8'h40) &&  (byte_length > 32'h0001_0000)) 
        	  illegal_length <= 1;
    end



always@(posedge clk_div or negedge w_rst_n)                              
    begin                                               
        if (!w_rst_n)   
            read_header_done <= 0;
        else if(cnt_header_bit == 8'h7e)
            read_header_done <= 1;
        else
            read_header_done <= 0;
    end   

always@(posedge clk_div or negedge w_rst_n)                                                                            
    begin                                                                                                              
        if (!w_rst_n)                                                                                                
            cnt_cmd_addr_as <= 6'h20;                                                                                  
        else if(read_header_done)                                                                        
            cnt_cmd_addr_as <= 6'h20;                                                                                  
        else if(((curstate == AS_READ) || (curstate == AS_READ_HEADER)) && |cnt_cmd_addr_as && spiclk_en)              
            cnt_cmd_addr_as <= cnt_cmd_addr_as - 6'b000001;                                                            
    end                                                                                                                


always@(posedge clk_div or negedge w_rst_n)                           
    begin                                                             
        if (!w_rst_n)                                        
            as_data_vld <= 0;
        else if((curstate == AS_READ) &&(cnt_cmd_addr_as == 6'b000000)) 
            as_data_vld <= 1;
        else
            as_data_vld <= 0;
    end
    
always@(posedge clk_div or negedge w_rst_n)                           
    begin                                                             
        if (!w_rst_n)                                        
            as_data <= 0;
        else if((curstate == AS_READ) &&(cnt_cmd_addr_as == 6'b000000)) 
            as_data <= i_flash_sdo;
        else
            as_data <= 0;
    end  


always@(posedge clk_div or negedge w_rst_n)                
    begin                                                  
        if (!w_rst_n)   
            cnt_ram_bit <= 0;
        else if(as_data_vld )                                 
            cnt_ram_bit <= cnt_ram_bit + 5'b00001;
    end

always@(posedge clk_div or negedge w_rst_n)                
    begin                                                  
        if (!w_rst_n)   
            o_ram_wr <= 0;
        else if(cnt_ram_bit == 5'h1f)
            o_ram_wr <= 1;
       else
            o_ram_wr <= 0;
    end 
     
reg [31:0] ram_wdata ;   
 
always@(posedge clk_div or negedge w_rst_n)                
    begin                                                  
        if (!w_rst_n) 
            ram_wdata <= 0;
        else if(as_data_vld) 
            ram_wdata <= {ram_wdata[30:0],as_data};
    end


assign o_ram_wdata  = {ram_wdata[7:0],ram_wdata[15:8],ram_wdata[23:16],ram_wdata[31:24]};    
 
always@(posedge clk_div or negedge w_rst_n)                 
    begin                                                   
        if (!w_rst_n)                                              
            o_ram_addr <= 0;
        else if(o_ram_wr)
            o_ram_addr <= o_ram_addr + 1;
    end

always@(posedge clk_div or negedge w_rst_n)
    begin                 
        if (!w_rst_n)
            tx_cmd_en <= 0;
        else if(bit_cnt8_cmd == 3'b000)
            tx_cmd_en <= 0;
        else if((bit_cnt8_cmd == 3'b111) && !w_flash_free)
            tx_cmd_en <= 1;
    end
        
always@(posedge clk_div or negedge w_rst_n)
    begin                 
        if (!w_rst_n)
            tx_addr_en <= 0;
        else if(bit_cnt24_addr == 5'b00000)
            tx_addr_en <= 0;
        else if(bit_cnt24_addr == 5'b11000)
            tx_addr_en <= 1;
    end


always@(posedge clk_div or negedge w_rst_n)
    begin                 
        if (!w_rst_n)
            bit_cnt8_cmd <= 3'h7;  
        else if(w_flash_free)
            bit_cnt8_cmd <= 3'h7;
        else if(!flash_csn && |bit_cnt8_cmd) 
            bit_cnt8_cmd <= bit_cnt8_cmd - 3'b001;
    end


always@(posedge clk_div or negedge w_rst_n)                 
    begin                                                   
        if (!w_rst_n) 
            bit_cnt24_addr <= 5'h1f;
        else if(w_flash_free)
            bit_cnt24_addr <= 5'h1f;
        else if(!flash_csn && w_addr_mode && |bit_cnt24_addr)
            bit_cnt24_addr <= bit_cnt24_addr - 3'b001;
    end

                                                                                          
always@(negedge clk_div or negedge w_rst_n)    
    begin                                     
        if (!w_rst_n)   
            o_flash_sdi <= 1'b0;
        else if(tx_cmd_en) 
            o_flash_sdi <= cmd_reg[bit_cnt8_cmd];  
        else if(tx_addr_en) 
            o_flash_sdi <= addr_reg_flash[bit_cnt24_addr];    
    end


always@(posedge clk_div or negedge w_rst_n)                    
    begin                                                       
        if (!w_rst_n)                                         
            flash_csn <= 1'b1;
        else if(w_flash_free)
            flash_csn <= 1'b1;
        else
            flash_csn <= 1'b0;
    end
                
always@(posedge clk_div or negedge w_rst_n)
    begin              
        if (!w_rst_n)   
            spiclk_en <= 0;
        else if(w_spiclk_clr)
            spiclk_en <= 0;
        else if(w_spiclk_vld)
            spiclk_en <= 1;
    end

always@(posedge clk_div or negedge w_rst_n)                     
    begin                                                       
        if (!w_rst_n)     
            cmd_reg <=  0;                               
        else if(curstate == READ_STATUS_REG)
            cmd_reg <= CMD_READ_STATUS_REG;
        else
            cmd_reg <= CMD_RDDATA;
    end

always@(posedge clk_div or negedge w_rst_n)                     
    begin                                                       
        if (!w_rst_n)     
            addr_reg_flash <= i_flash_bias;
        else if(curstate == AS_READ)
            addr_reg_flash <= i_flash_bias + 24'h10;        
    end   

always@(posedge clk_div or negedge w_rst_n)                        
    begin                                                          
        if (!w_rst_n)                                            
            cnt_read_status <= 0;                                  
        else if(read_status_done == 1'b1)                        
            cnt_read_status <= 0;                                  
        else if((flash_csn == 1'b0) && (curstate == READ_STATUS_REG))
            cnt_read_status <= cnt_read_status + 4'b0001;
        else
            cnt_read_status <= 0;              
    end                                                            

always@(posedge clk_div or negedge w_rst_n)                              
    begin                                               
        if (!w_rst_n)   
            read_status_done <= 0;
        else if(cnt_read_status == 4'b1110)
            read_status_done <= 1;
        else
            read_status_done <= 0;
    end                             

always@(posedge clk_div or negedge w_rst_n)              
    begin                                                
        if (!w_rst_n) 
            flash_busy <= 1;
        else if(cnt_read_status == 4'b1111)
            flash_busy <= i_flash_sdo; 
        else
            flash_busy <= 1;
    end                                  
                                                                                                                                                                                                     
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////               
//////////////////////////////////////jtag master ctrl ////////////////////////////////////////////////////////////               
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////      
always@(negedge o_tck or negedge w_rst_n)                                        
    begin                                                                     
        if (!w_rst_n)                                                         
            begin                                                             
                remap_begin_d1 <= 0;                                            
                remap_begin_d2 <= 0;                                            
            end                                                               
        else                                                                  
            begin                                                             
                remap_begin_d1 <= (curstate == HOLD_AS) ;                                    
                remap_begin_d2 <= remap_begin_d1;                                 
            end                                                               
    end                                                                       

         
always@(negedge o_tck or negedge w_rst_n)                                                                                         
    begin                                                                                                                         
        if(!w_rst_n)                                                                                                              
           cnt_reset_tap <= 0;                                                                                                    
        else if(cnt_reset_tap == 3'b100)                                                                                          
           cnt_reset_tap <= 0;                                                                                                    
        else if(curr_tap_state == RESET_JTAG_TAP)                                                                                 
           cnt_reset_tap <= cnt_reset_tap + 3'b001;                                                                               
    end                                                                                                                           
    
    
always@(negedge o_tck or negedge w_rst_n)                                                                                  
    begin                                                                                                                  
        if(!w_rst_n)                                                                                                       
            cnt_state_incdr <= 0;                                                                                       
        else if(cnt_state_incdr == CNT_TMS_REG_IRDR)                                                                 
            cnt_state_incdr <= 0;                                                                                       
        else if((curr_tap_state == ISC_DPACC_CTST) ||(curr_tap_state == ISC_DPACC_AP) || (curr_tap_state == ISC_APACC_0) || (curr_tap_state == ISC_APACC_1))             
            cnt_state_incdr <= cnt_state_incdr + 1;                                                                  
    end        
    
    

always@(negedge o_tck or negedge w_rst_n)
    begin
        if(!w_rst_n)
            o_tms <= 1;
        else if(curr_tap_state == RESET_JTAG_TAP)
            begin
                if(cnt_reset_tap == 3'b100)
                    o_tms <= 0;
                else
                    o_tms <= 1;
             end
        else if((curr_tap_state == ISC_DPACC_CTST) ||(curr_tap_state == ISC_DPACC_AP) || (curr_tap_state == ISC_APACC_0) || (curr_tap_state == ISC_APACC_1))
            o_tms <= wm_tms_reg_irdr[49 - cnt_state_incdr];
    end

always@(negedge o_tck or negedge w_rst_n)
    begin
        if(!w_rst_n)
            o_tdi <= 0;
        else if(cnt_state_incdr >= 4 && cnt_state_incdr <= 7)
            begin
               if((curr_tap_state == ISC_DPACC_CTST) ||(curr_tap_state == ISC_DPACC_AP))
                    o_tdi <= wm_isc_dpacc_ir[cnt_state_incdr - 4 ];
                else if((curr_tap_state == ISC_APACC_0)||(curr_tap_state == ISC_APACC_1))
                    o_tdi <= wm_isc_apacc_ir[cnt_state_incdr - 4 ];
            end
        else if(cnt_state_incdr >= 13 && cnt_state_incdr <= 47 )
                    begin
                        if(curr_tap_state == ISC_DPACC_AP)
                            o_tdi <= wm_isc_dpacc_dr[cnt_state_incdr - 13]; 
                        else if(curr_tap_state == ISC_DPACC_CTST)
                            o_tdi <= wm_isc_apacc_dr_ctst[cnt_state_incdr - 13];
                        else if(curr_tap_state == ISC_APACC_0)
                            o_tdi <= wm_isc_apacc_dr_0[cnt_state_incdr - 13];  
                        else if(curr_tap_state == ISC_APACC_1)                    
                            o_tdi <= wm_isc_apacc_dr_1[cnt_state_incdr - 13];                
                    end                                         
    end    


always@(negedge o_tck or negedge w_rst_n)
    begin
        if(!w_rst_n)
            first_dpacc <= 0;
        else if(curr_tap_state == CFG_FINISH)
            first_dpacc <= 0;    
        else if((curr_tap_state == ISC_DPACC_AP) && (cnt_state_incdr == CNT_TMS_REG_IRDR))
            first_dpacc <= 1;
    end  
  
  
                                                                                        
always@(negedge o_tck or negedge w_rst_n)
    begin
        if(!w_rst_n)
            curr_tap_state <= NOP;
        else
            curr_tap_state <= next_tap_state;
    end

always @ ( * )
    begin
        case (curr_tap_state)

            NOP :                begin   
            	                       if(remap_begin_d1 && !remap_begin_d2)
                                         next_tap_state = RESET_JTAG_TAP ;
                                     else
                                         next_tap_state = NOP ;
                                 end

            RESET_JTAG_TAP:      begin
                                     if(cnt_reset_tap == 3'b100)
                                         next_tap_state = ISC_DPACC_CTST;
                                       else
                                         next_tap_state = RESET_JTAG_TAP;
                                 end
                                 
             ISC_DPACC_CTST:     begin
             	                       if(cnt_state_incdr == CNT_TMS_REG_IRDR)    
             	                           next_tap_state = ISC_DPACC_AP; 
             	                       else
             	                           next_tap_state = ISC_DPACC_CTST;
             	                   end          
             	                                                                       
                                 
             ISC_DPACC_AP :      begin
                                      if(cnt_state_incdr == CNT_TMS_REG_IRDR)
                                          begin
                                              if(first_dpacc == 1'b1)
                                                  next_tap_state = ISC_APACC_1;
                                              else     
                                                  next_tap_state = ISC_APACC_0;    
                                          end
                                      else
                                          next_tap_state = ISC_DPACC_AP;
                                  end          
                                 
                                 
            ISC_APACC_0      :  begin                                                     
           	                         if(cnt_state_incdr == CNT_TMS_REG_IRDR)               
           	                             next_tap_state = ISC_DPACC_AP;                       
           	                         else                                                  
           	                             next_tap_state = ISC_APACC_0;                       
           	                    end  
           	                     
            ISC_APACC_1      :  begin                                                                             
                                     if(cnt_state_incdr == CNT_TMS_REG_IRDR)                                      
                                         next_tap_state = CFG_FINISH;                                              
                                     else                                                                         
                                         next_tap_state = ISC_APACC_1;                                            
                                end                                  
           	                                                                                                  	                                	                                	                                  	                     
           	CFG_FINISH     :    begin
           		                       next_tap_state = NOP;
           		                  end           		
           		                                                          
            	
            default:              next_tap_state = NOP;
        endcase

    end      
    
always@(negedge o_tck or negedge w_rst_n)
    begin
        if(!w_rst_n)         
            o_ini_ip <= 1;
        else if(curr_tap_state == CFG_FINISH)
            o_ini_ip <= 0;
    end
    
endmodule                                                                                             
////////////////////////////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////////////////////////
module GCKESF(input wire E,
              input wire TE,
              input wire CK,
              output wire Q);
              

wire d;

reg dq;

assign d = E || TE;
/*
always@( * )
    begin
    	  if(!CK)
    	      dq = d ;
    end    
*/
always@(negedge CK)
    dq <= d ;

assign Q = dq && CK;

endmodule 
